package com.qingyun.form.items

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import com.qingyun.form.base.FormGroup
import com.qingyun.form.base.FormType
import com.qingyun.form.base.FormViewHolder
import com.qingyun.form.internal.IFormDataBinding
import com.qingyun.form.listener.IFormChangedListener
import com.qingyun.form.validator.BaseFormValidator
import com.qingyun.form.validator.RequiredFormValidator
import java.util.Objects

abstract class BaseFormItem(
    val label: String,//表单标签，展示的标题
    val name: String,//表单名称，表单字段名称
    var value: String?,//表单值,以String类型保存，获取时需要手动转换
) {
    abstract val formType: FormType
    abstract val layoutId: Int

    /**
     * 是否可用，false时不可编辑
     */
    var enabled: Boolean = true

    /**
     * 是否为只读
     */
    var viewOnly: Boolean = false

    /**
     * 是否为必填项
     */
    var required: Boolean = false
        set(value) {
            field = value
            //如果是必填项，并且没有校验器，则添加必填校验器
            if (value && this.mValidator == null) {
                this.mValidator = RequiredFormValidator()
            }
            //如果不是必填项，并且有必填校验器，则移除必填校验器
            if (!value && this.mValidator is RequiredFormValidator) {
                this.mValidator = null
            }
        }

    /**
     * 表单提示信息
     */
    open var hint: String? = null
        get() = if (field.isNullOrEmpty()) "请输入$label" else field

    /** 表单组 */
    internal var formGroup: FormGroup? = null
    protected var fragmentManager: FragmentManager? = null
    protected var dataBinding: IFormDataBinding? = null

    val position: Int
        get() = formGroup?.indexOf(this) ?: -1

    /**
     * 表单校验器
     */
    var mValidator: BaseFormValidator? = null

    /**
     * 表单监听器
     */
    private var mListener: IFormChangedListener? = null

    /**
     * 表单值过滤器
     */
    private var mFilter: IFormValueFilter? = null

    /**
     * 父表单
     */
    internal var parent: BaseFormItem? = null

    fun setFormChangedListener(onFromChanged: (item: BaseFormItem, String?, String?) -> Unit) {
        this.mListener = object : IFormChangedListener {
            override fun onValueChanged(item: BaseFormItem, oldValue: String?, newValue: String?) {
                onFromChanged(item, oldValue, newValue)
            }
        }
        this.mListener!!.onValueChanged(this, this.value, null)
    }

    protected fun onValueChanged(value: String?, refreshMe: Boolean = false) {
        val filterValue = mFilter?.filter(this, value) ?: value
        val oldValue = this.value
        this.value = filterValue
        if (value != filterValue) {
            selfRefresh()
        } else if (refreshMe && oldValue != filterValue) {
            selfRefresh()
        }
        this.mListener?.onValueChanged(this, value, this.value)
        this.dataBinding?.setFormValue(this)
    }

    private fun selfRefresh() {
        formGroup?.refreshItem(this)
    }

    override fun equals(other: Any?): Boolean {
        if (other === this) {
            return true
        }
        if (other == null || other.javaClass != this.javaClass) {
            return false
        }
        other as BaseFormItem
        return this.name == other.name
    }

    override fun hashCode(): Int {
        return Objects.hashCode(name)
    }

    override fun toString(): String {
        return "${this.javaClass.simpleName}: label=$label, name=$name, value=$value, enabled=$enabled, viewOnly=$viewOnly, required=$required"
    }

    /**
     * 添加到FormGroup时触发调用
     */
    open fun onFormItemAdd(index: Int, formGroup: FormGroup) {
        this.formGroup = formGroup
    }

    open fun onFormItemRemoved() {
        this.formGroup = null
        this.dataBinding = null
        this.fragmentManager = null
        this.parent = null
        this.mFilter = null
        this.mListener = null
        this.mValidator = null
        this.value = null
    }

    /**
     * 创建 ViewHolder
     */
    open fun onCreateViewHolder(inflater: LayoutInflater, group: ViewGroup): FormViewHolder {
        return FormViewHolder(inflater, group, layoutId)
    }

    fun onBindViewHolderOnAdapter(holder: FormViewHolder) {
        //取消绑定的事件
        onUnBindViewEvent(holder)
        holder.setTitle(this.label)
        holder.setValue(this.value)
        holder.setViewOnly(this.viewOnly)
        holder.setRequired(this.required)
        //绑定View
        onBindViewHolder(holder)
        //非只读状态时，需要绑定事件
        if (!this.viewOnly) {
            onBindViewEvent(holder)
        }
    }

    /**
     * 获取Title布局的宽度
     */
    open fun getTitleLayoutWidth(holder: FormViewHolder): Int = 0

    /**
     * 布局管理器[com.qingyun.form.base.FormLayoutManager]重新布局时调用
     */
    protected open fun onLayoutChildren(holder: FormViewHolder) = Unit

    protected abstract fun onBindViewHolder(holder: FormViewHolder)

    /**
     * 绑定 View 的事件
     */
    protected open fun onBindViewEvent(holder: FormViewHolder) = Unit

    /**
     * 取消 View 的事件绑定
     */
    protected open fun onUnBindViewEvent(holder: FormViewHolder) = Unit

    /**
     * 回收View时触发
     */
    open fun onRecycled(holder: FormViewHolder) {
        onUnBindViewEvent(holder)
    }

    /**
     * 当 View 展示时触发
     */
    open fun onViewAttachedToWindow(holder: FormViewHolder) {
        if (!viewOnly) {
            onBindViewEvent(holder)
        }
    }

    open fun onViewDetachedFromWindow(holder: FormViewHolder) {
        onUnBindViewEvent(holder)
    }

    fun layout(holder: FormViewHolder) {
        if (holder.maxTitleLayoutWidth <= 0) {
            return
        }
        onLayoutChildren(holder)
    }

    /**
     * 查找焦点View
     */
    fun focusSearch(holder: FormViewHolder): View? {
        return null
    }

    /**
     * 渲染时触发
     */
    open fun onFormRender(manager: FragmentManager, binding: IFormDataBinding?) {
        this.fragmentManager = manager
        this.dataBinding = binding
    }
}